import WorkerBase
import MSData
import MSLogger
import socket

import sys
import datetime
import time
import pdb


class Worker(WorkerBase.WorkerBase):
    def __init__(self, Host, Port):
        self.host = Host
        self.port = Port
        self.connection = None

    def getConnectionName(self):
        return '(%s:%d)' % (str(self.host), int(self.port))

    def getConnection(self):
        sock = socket.socket()
        sock.connect((str(self.host), int(self.port)))
        return sock
    
    def isConnectionGood(self):
        return False

    def sendEvent(self, sock, e):
        #pdb.set_trace()
        buf = ''
        buf += chr(0x40)
        buf += chr(0xFA)
        buf += chr(0x06)
        
        def asciiconvert(val, nbytes):
            buf = ''
            codes = \
            {
             '0' : 0x30,
             '1' : 0x31,
             '2' : 0x32,
             '3' : 0x33,
             '4' : 0x34,
             '5' : 0x35,
             '6' : 0x36,
             '7' : 0x37,
             '8' : 0x38,
             '9' : 0x39
            }
            tmp = str(val)
            for c in reversed(tmp):
                code = codes.get(c, None)
                if not code: raise RuntimeError('asciiconvert: cannot find code for "%s"' % (c))
                buf = chr(code) + buf
                if len(buf) >= nbytes: break
            while len(buf) < nbytes:
                buf = chr(codes['0']) + buf
            return buf            
        
        def idconvert(val, nbytes, straightOrder=True):
            tmp = str(hex(val))
            tmp = tmp.replace('0x','').replace('L','')
            pair = []
            pairs = []
            for c in reversed(tmp):
                c = int(c, 16)
                pair.append(c)
                if len(pair) == 2:
                    pair.reverse()
                    pairs.append(pair)
                    pair = []
                if len(pairs) >= nbytes: break
            while len(pairs) < nbytes:
                if len(pair) == 1:
                    pair.append(0)
                    pair.reverse()
                    pairs.append(pair)
                else:
                    pairs.append([0,0])
            if straightOrder: pairs.reverse()
            
            buf = ''
            for p in pairs:
                buf += chr((p[0] << 4) | p[1])
            return buf
        
        def hexconvert(val, nbytes, straightOrder=True):
            tmp = str(val)
            #if len(tmp) > nbytes * 2: raise RuntimeError('hexconvert: size(%d) exceeded %d' % (nbytes, len(tmp)))
            pair = []
            pairs = []
            for c in reversed(tmp):
                c = int(c)
                pair.append(c)
                if len(pair) == 2:
                    pair.reverse()
                    pairs.append(pair)
                    pair = []
                if len(pairs) >= nbytes: break
            while len(pairs) < nbytes:
                if len(pair) == 1:
                    pair.append(0)
                    pair.reverse()
                    pairs.append(pair)
                else:
                    pairs.append([0,0])
            if straightOrder: pairs.reverse()
            
            buf = ''
            for p in pairs:
                buf += chr((p[0] << 4) | p[1])
            return buf
        
        #4,5 - object id
        buf += hexconvert(e.objectId, 2)
    
        #6,7 - contact id type
        try:
            tmp = str(e.contactIdType)
            tmp = tmp[3] + tmp[0:3]
            buf += hexconvert(int(tmp), 2)
        except Exception, err:
            MSLogger.logError('unproper_contact_id error: %s' % str(err))
            raise err
        
        #8 - group
        buf += hexconvert(e.contactIdGroup, 1)
        #9,10 - zona
        buf += hexconvert(e.contactIdZona, 2)
        #11:14 - event id
        buf += idconvert(e.eventIdToKirill, 4, False)
        #15:22 - object uid
        #buf += hexconvert(e.objectUID, 8)
        #pdb.set_trace()
        buf += asciiconvert(e.objectUID, 8)
        #buf += chr(0x00) + chr(0x00) + chr(0x00) + chr(0x00) + chr(0x00) + chr(0x00) + chr(0x00) + chr(0x01)
        #23:26 - unix time
        stamp = int(time.mktime(e.eventGenerateTime.timetuple()))

        buf += chr(stamp & 0x000000FF)        
        buf += chr((stamp & 0x0000FF00) >> 8)
        buf += chr((stamp & 0x00FF0000) >> 16)
        buf += chr((stamp & 0xFF000000) >> 24)
        #time.sleep(1)
        sock.send(buf)
        buf = sock.recv(2)
        if buf != 'OK': raise RuntimeError('no acknowledge')
        #time.sleep(1)
        #MSLogger.logInfo('DEBUG: event(%s) sent' % str(e.objectId))

    def writeEventsStatic(self, MSObjects):
        for obj in MSObjects:
            try:
                doneNum         = 0
                obj.canClearPGSMEvents  = True
                obj.eventsPGSM.sort()
                for e in obj.eventsPGSM:
                    try:
                        e.userWriterId = "magic writer"
                        conn = self.getConnection()
                        self.sendEvent(conn, e)
                        doneNum += 1
                    except Exception, err:
                        MSLogger.logError('Worker::writeEventsStatic: object(%s) PGSM event processing failed: %s' % (str(obj.objectPCNId), str(err)))
                        obj.canClearPGSMEvents = False
                        continue
                if len(obj.eventsPGSM) > 0:
                    MSLogger.logInfo('Worker::writeEventsStatic: object(%s) PGSM done(%d:%d)' % (str(obj.objectPCNId), doneNum, len(obj.eventsPGSM)))
                else:
                    MSLogger.logDebug('Worker::writeEventsStatic: object(%s) PGSM done(%d:%d)' % (str(obj.objectPCNId), doneNum, len(obj.eventsPGSM)))


                doneNum         = 0
                obj.canClearContactIdEvents  = True
                obj.eventsContactId.sort()
                for e in obj.eventsContactId:
                    try:
                        e.userWriterId = "magic writer"
                        conn = self.getConnection()
                        self.sendEvent(conn, e)
                        doneNum += 1
                    except Exception, err:
                        MSLogger.logError('Worker::writeEventsStatic: object(%s) ContactId event processing failed: %s' % (str(obj.objectPCNId), str(err)))
                        obj.canClearContactIdEvents = False
                        #JEKA
                        continue
                if len(obj.eventsContactId) > 0:
                    MSLogger.logInfo('Worker::writeEventsStatic: object(%s) ContactId done(%d:%d)' % (str(obj.objectPCNId), doneNum, len(obj.eventsContactId)))
                else:
                    MSLogger.logDebug('Worker::writeEventsStatic: object(%s) ContactId done(%d:%d)' % (str(obj.objectPCNId), doneNum, len(obj.eventsContactId)))

                doneNum         = 0
                obj.canClearBolidEvents  = True
                obj.eventsBolid.sort()
                for e in obj.eventsBolid:
                    try:
                        e.userWriterId = "magic writer"
                        conn = self.getConnection()
                        self.sendEvent(conn, e)
                        doneNum += 1
                    except Exception, err:
                        MSLogger.logError('Worker::writeEventsStatic: object(%s) Bolid event processing failed: %s' % (str(obj.objectPCNId), str(err)))
                        self.canClearBolidEvents = False
                        continue
                if len(obj.eventsBolid):
                    MSLogger.logInfo('Worker::writeEventsStatic: object(%s) Bolid done(%d:%d)' % (str(obj.objectPCNId), doneNum, len(obj.eventsBolid)))
                else:
                    MSLogger.logDebug('Worker::writeEventsStatic: object(%s) Bolid done(%d:%d)' % (str(obj.objectPCNId), doneNum, len(obj.eventsBolid)))

            except Exception, err:
                MSLogger.logError('Worker::writeEventsStatic: object(%s) processing failed: %s' % (str(obj.objectPCNId), str(err)))
                continue
        return
